#ifndef __SMS_CLIENT__
#define __SMS_CLIENT__


#include "sms_helper.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>


namespace sms {


class Client
{

public:
    Client(
        std::string request_url,
        std::string request_type,
        std::string response_type,
        bool request_once=false,
        std::string ip="127.0.0.1",
        int port=9094
    );
    ~Client();
    void kill();
    nlohmann::json request(nlohmann::json json_msg, int timeout=5);
    nlohmann::json request_once(nlohmann::json json_msg, int timeout=5);
    void recv_loop();
    void send_loop();
    void heartbeat_loop();
    void join();
    nlohmann::json cvimg2sms_mem(const cv::Mat& cvimg, const std::string frame_id="camera");

private:
    bool _link();
    void _heartbeat();
    void _close_socket();
    bool _parse_msg(std::string msg);

    std::string _request_url;
    std::string _request_type;
    std::string _response_type;
    std::string _ip;
    int _port;
    bool _request_once;
    std::mutex _send_mtx;
    std::mutex _ids_mtx;
    std::mutex _queue_mtx;
    std::queue<nlohmann::json> _send_queue;
    std::condition_variable _cv;

    std::mutex _response_mtx;
    std::queue<nlohmann::json> _response_queue;
    std::condition_variable _response_cv;

    double _last_send_time;
    double _last_upload_time;
    bool _force_quit;
    bool _heartbeat_running;
    bool _running;

    std::string _last_msg;
    int _last_msg_len;
    int _upload_id;

    bool _suspended;
    int _error_cnt;

    int _client_socket;
    struct sockaddr_in _server_addr;
    char* _buf;

    std::thread* _recv_t;
    std::thread* _send_t;
    std::thread* _heartbeat_t;

    bool _use_shm;
    std::string _shm_name;
};


}

#endif
